from flask import Flask, request, jsonify
from flask_cors import CORS
from util import send_email_to, generate_verify_code, generate_order_code
import datetime
import database
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity, verify_jwt_in_request
from decimal import Decimal
from werkzeug.utils import secure_filename
import os
import uuid

app = Flask(__name__)
# 存储验证码和生成时间的字典
app.config['JWT_SECRET_KEY'] = 'wsad1234&'

UPLOAD_FOLDER = 'static/'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# 检查文件是否允许的扩展名
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


jwt = JWTManager(app)

verification_store = {}

# 解决跨域
CORS(app)

@app.before_request
def handle_options_requests():
    if request.method == 'OPTIONS':
        print("options executed")
        response = {
            'code': 200,
        }
        return jsonify(response)


@jwt_required()
@app.route('/upload', methods=['POST'])
def upload_file():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        if 'file' not in request.files:
            return jsonify({
                'code': 300,
                'msg': 'no file uploaded',
                'data': None
            })
        
        file = request.files['file']

        # 如果用户没有选择文件，文件名为空
        if file.filename == '':
            return jsonify({
                'code': 300,
                'msg': 'no file uploaded',
                'data': None
            })

        # check file format
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            ext = filename.rsplit('.', 1)[1].lower()  # 获取文件扩展名
            unique_filename = f"{uuid.uuid4().hex}.{ext}"  # 生成唯一文件名

            # save file
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], unique_filename))

            # update user head in db
            database.update_avatar(database.create_connection(),email, f"static/{unique_filename}")
            return jsonify({
                'code': 200,
                'msg': '',
                'data': None
            })
        else:
            return jsonify({
                'code': 300,
                'msg': 'file foamat not valid',
                'data': None
            })
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)




@jwt_required()
@app.route('/update_nickname', methods=['POST'])
def update_nickname():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
    
        body = request.get_json()
        nick_name = body['nickName']
        # check file format
        result = database.update_nick_name(database.create_connection(), email, nick_name)
        return jsonify({
                'code': 200,
                'msg': '',
                'data': result
        })
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)
    

@jwt_required()
@app.route('/update_password', methods=['POST'])
def update_password():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        password = body['password']
        newpass = body['newpass']
        user_info = database.query_user(database.create_connection(), email)
        if user_info['password'] != password:
            return jsonify({
                'code': 300,
                'msg': 'old password error',
                'data': None
            })
        
        result = database.update_password(database.create_connection(), email, newpass)
        return jsonify({
                'code': 200,
                'msg': '',
                'data': result
        })
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)


@app.route("/send_verify_code", methods=['POST'])
def send_verify_code():
    body = request.get_json()
    email = body['email']
    result = database.query_user(database.create_connection(), email)
    if result is not None:
        response = {
            'code': 101,
            'msg': 'email has been registered',
            'data': None
        }
        return jsonify(response)
    
    verify_code = generate_verify_code()
    print(f"verify_code: {verify_code}")
    now = datetime.datetime.now()
    verification_store[email] = verify_code
    expire_key = f'{email}_{verify_code}'
    verification_store[expire_key] = now
    send_email_to(email, verify_code)
    response = {
        'code': 200,
        'msg': f'verify code has been send to email {email}',
        'data': None
    }
    return jsonify(response)



@app.route("/category_list", methods=['POST'])
def category_list():
    body = request.get_json()
    category = body['category']
    result = database.query_sub_category(database.create_connection(), category)
    response = {
            'code': 200,
            'msg': '',
            'data': result
        }
    return jsonify(response)

@app.route("/food_list", methods=['POST'])
def food_list():
    body = request.get_json()
    category = body['category']
    type = body['type']

    result = database.query_food(database.create_connection(), category, type)
    response = {
            'code': 200,
            'msg': '',
            'data': result
        }
    return jsonify(response)


@app.route("/sign_up", methods=['POST'])
def sign_up():
    body = request.get_json()
    email = body['email']
    result = database.query_user(database.create_connection(), email)
    if result is not None:
        response = {
            'code': 101,
            'msg': 'email has been registered',
            'data': None
        }
        return jsonify(response)
    
    verify_code = verification_store[email]
    if verify_code is None:
        response = {
            'code': 101,
            'msg': 'no verify code, please get code first',
            'data': None
        }
        return jsonify(response)
    

    if body['verify_code'] != verify_code:
        response = {
            'code': 101,
            'msg': 'verify code is incorrect!',
            'data': None
        }
        return jsonify(response)
    
    expire_key = f'{email}_{verify_code}'
    generated_time = verification_store[expire_key]
    now = datetime.datetime.now()

    # verify code has expired
    if (now - generated_time).seconds >= 300:  # 300秒即5分钟
        del verification_store[expire_key]  # 过期后从存储中删除
        del verification_store[email]
        response = {
            'code': 101,
            'msg': 'verify code is expired, please retry!',
            'data': None
        }
        return jsonify(response)
    
    body['nick_name'] = f'User_{verify_code}'
    body['head_img'] = 'static/default-user.png'
    if database.add_user(database.create_connection(), body):
        response = {
            'code': 200,
            'msg': 'register successfully',
            'data': None
        }
    else:
        response = {
            'code': 101,
            'msg': 'register failed!',
            'data': None
        }
    return jsonify(response)

# session 
# cookie  server 

@app.route("/sign_in", methods=['POST'])
def sign_in():
    body = request.get_json()
    email = body['emailVal']
    user = database.query_user(database.create_connection(), email)
    if user is None:
        response = {
            'code': 300,
            'msg': 'email has not registered',
            'data': None
        }
    else:
        if user['password'] != body['passwordVal']:
            response = {
                'code': 300,
                'msg': 'password not correct',
                'data': None
            }
        else:
            access_token = create_access_token(identity=email)
            response = {
                'code': 200,
                'msg': '',
                'data': access_token,
                'role': user['role']
            }
    return jsonify(response)


@jwt_required()
@app.route("/readd_to_cart", methods=['POST'])
def readd_to_cart():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        result = True
        for param in body:
            param['customer_id'] = email
            result = database.add_to_cart2(database.create_connection(), param)
        response = {
            'code': 200,
            'msg': '',
            'data': result
        }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)


@jwt_required()
@app.route("/add_to_cart", methods=['POST'])
def add_to_cart():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        body['customer_id'] = email
        if database.add_to_cart(database.create_connection(), body) == True:
            response = {
                'code': 200,
                'msg': 'add successfully',
                'data': None
            }
        else:
            response = {
                'code': 300,
                'msg': 'add to cart failed',
                'data': None
            }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)
    


@app.route("/update_cart_count", methods=['POST'])
def update_cart_count():
    body = request.get_json()
    if database.update_cart_count(database.create_connection(), body['customer_id'], body['food_id'], body['value']) == True:
        response = {
            'code': 200,
            'msg': 'update successfully',
            'data': None
        }
    else:
        response = {
            'code': 300,
            'msg': 'update failed',
            'data': None
        }
    return jsonify(response)


@jwt_required()
@app.route("/query_cart", methods=['POST'])
def query_cart():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        cart_goods = database.query_cart(database.create_connection(), email)
        response = {
            'code': 200,
            'msg': '',
            'data': cart_goods
        }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)



@jwt_required()
@app.route("/create_order", methods=['POST'])
def create_order():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        category = body['category']
        # print(category)
        cart_goods = database.query_cart(database.create_connection(), email)
        
        target_foods = []
        total_price = Decimal(0.0)

        for good in cart_goods:
            # print(good['category'] == category)
            if good['category'] == category:
                total_price = total_price + (good['price'] * Decimal(good['number']))
                target_foods.append(good)
        
        print('total_price:', total_price)
        ## 生成订单编号
        order_id = generate_order_code()
        # 保存订单和订单明细
        order_params = {
            'order_id': order_id,
            'customer_id': email,
            'total_price': total_price,
            'category': category
        }

        if database.create_order(database.create_connection(), order_params):
            # 生成订单明细
            for item in target_foods:
                detail_params = {
                    'food_id': item['foodId'],
                    'number': item['number'],
                    'order_id': order_id,
                }
                database.create_order_detail(database.create_connection(), detail_params)
                # 删除购物车对应的商品
                database.delete_cart_food(database.create_connection(), item['cartId'])


        response = {
            'code': 200,
            'msg': '',
            'data': order_id
        }
        return jsonify(response)
    except Exception as e:
        print(e)
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)


@jwt_required()
@app.route("/query_order", methods=['POST'])
def query_order():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        order_id = body['order_id']
        result = database.query_order(database.create_connection(), order_id)
        response = {
            'code': 200,
            'msg': '',
            'data': result
        }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)
    

@jwt_required
@app.route("/query_self_order", methods=['POST'])
def query_self_order():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        order_list = database.query_customer_order(database.create_connection(), email)
        for order_item in order_list:
            item_list = database.query_order_detail(database.create_connection(), order_item['id'])
            order_item['items'] = item_list

        response = {
            'code': 200,
            'msg': '',
            'data': order_list
        }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)


@jwt_required
@app.route("/query_all_order", methods=['POST'])
def query_all_order():
    try:
        verify_jwt_in_request()
        order_list = database.query_all_order(database.create_connection())
        for order_item in order_list:
            item_list = database.query_order_detail(database.create_connection(), order_item['id'])
            order_item['items'] = item_list

        response = {
            'code': 200,
            'msg': '',
            'data': order_list
        }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)


@jwt_required
@app.route("/update_order", methods=['POST'])
def update_order():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        if database.update_order_status(database.create_connection(), body):
            response = {
                'code': 200,
                'msg': '',
                'data': None
            }
        else:
            response = {
                'code': 300,
                'msg': 'Order Info Error',
                'data': None
            }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)


@jwt_required
@app.route("/add_card", methods=['POST'])
def add_card():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        body['customer_id'] = email
        result = database.add_credit_card(database.create_connection(), body)
        response = {
            'code': 200,
            'msg': '',
            'data': result
        }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)
    

@jwt_required
@app.route("/update_card", methods=['POST'])
def update_card():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        result = database.update_credit_card(database.create_connection(), body['cardNo'], email)
        response = {
            'code': 200,
            'msg': '',
            'data': result
        }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)
    

@jwt_required
@app.route("/delete_card", methods=['POST'])
def delete_card():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        body = request.get_json()
        result = database.delete_credit_card(database.create_connection(), body['cardNo'])
        response = {
            'code': 200,
            'msg': '',
            'data': result
        }
        return jsonify(response)
    except Exception as e:
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)



@jwt_required
@app.route("/current_user", methods=['POST'])
def current_user():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        user_info = database.query_user(database.create_connection(), email)
        response = {
            'code': 200,
            'msg': '',
            'data': user_info
        }
        return jsonify(response)
    except Exception as e:
        print(e)
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)
    

@jwt_required
@app.route("/query_card", methods=['POST'])
def query_card():
    try:
        verify_jwt_in_request()
        email = get_jwt_identity()
        card_list = database.query_credit_card(database.create_connection(), email)
        response = {
            'code': 200,
            'msg': '',
            'data': card_list
        }
        return jsonify(response)
    except Exception as e:
        print(e)
        response = {
                'code': 401,
                'msg': 'NO LOGIN',
                'data': None
        }
        return jsonify(response)
    

@app.route("/query_open_time", methods=['POST'])
def query_open_time():
    result = database.query_open_time(database.create_connection())
    response = {
        'code': 200,
        'msg': '',
        'data': result
    }
    return jsonify(response)

app.run()